<template>
  <div class="rightMenuWrapper" @contextmenu.prevent="handleRightClick" @click="handleClick">
    <slot :data="data"></slot>
    <ul class="rightMenu" v-if="showMenu" :style="pos" @click="menuClick">
      <template v-for="(menu, index) in computedMenus">
        <li v-if="menu.code !== 'line'" :code="menu.code" :key="index" :index="index">
          {{ menu.name }}
        </li>
        <li v-else class="line" :key="menu.code"></li>
      </template>
    </ul>
  </div>
</template>
<script lang="ts" setup>
//工具库
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance, computed } from 'vue'
import PubSub from 'pubsub-js'
const emit = defineEmits(['menuClick'])
const props = defineProps({
  menus: {
    type: Array,
    default: () => []
  },
  data: {
    type: Object,
    default: () => {}
  }
})
const computedMenus = computed(() => {
  const menuList = props.menus
  menuList.splice(props.menus.length - 1, 0, { code: 'line' })
  return menuList
})
//组件
//属性
const { uid } = getCurrentInstance()
const showMenu = ref<Boolean>(false)
const pos = reactive({ top: '', left: '' })
const { innerWidth, innerHeight } = window
const menuWidth = 55,
  menHeight = 89
//方法
const handleRightClick = (e: any) => {
  if (props.menus.length === 0) return
  // 此处需要计算点击的位置（可能会超出屏幕边界）
  const { clientX, clientY } = e // 距离左侧和右侧可视区域的距离
  //如果当前点击的位置+组件的宽度大于屏幕宽度
  if (clientX + menuWidth > innerWidth) {
    pos.left = `${clientX - menuWidth}px`
  } else {
    pos.left = `${clientX}px`
  }
  //如果当前点击的位置+组件的高度大于屏幕高度
  if (clientY + menHeight > innerHeight) {
    pos.top = `${clientY - menHeight}px`
  } else {
    pos.top = `${clientY}px`
  }
  console.log(clientX, clientY)
  showMenu.value = true
  // 发布消息取消其他的右键菜单
  PubSub.publish('canncelRightMenu', { componentId: uid })
}
const handleClick = () => {
  if (showMenu.value) return (showMenu.value = false)
}
// 右键菜单时间
const menuClick = (event: any) => {
  props.menus[event.target.getAttribute('index')]?.action(props.data)
}
// 生命周期
onMounted(() => {
  PubSub.subscribe('canncelRightMenu', (msg: string, data: any) => {
    data.componentId !== uid ? (showMenu.value = false) : (showMenu.value = true)
  })
})
// 在组件销毁时清理定时器
onUnmounted(() => {
  PubSub.unsubscribe('canncelRightMenu')
})
</script>
<style lang="less" scoped>
.rightMenuWrapper {
  flex: 1;
  .rightMenu {
    background-color: white;
    position: fixed;
    list-style-type: none;
    padding: 8px 10px;
    border-radius: 5px;
    box-shadow: 2px 2px 10px #ccc;
    li {
      padding: 7px 5px;
      font-size: 13px;
      cursor: pointer;
      border-radius: 2px;
      &:hover {
        background-color: #e7e7e7;
      }
      &.line {
        height: 0.5px;
        padding: 0;
        width: 54%;
        margin: 4px auto;
        background-color: #d9d9d9;
      }
    }
  }
}
</style>
